#!/bin/bash

# ==============================================================================
# A wrapper script for common ipmitool functions.
# Version 3: Supports flexible order for IP address and command.
# Handles special security requirements for SOL command.
# Uses array for robust argument passing.
# ==============================================================================

# --- Configuration ---
DEFAULT_PASS="asdfQWER@1234"
IPMI_USER="root"
IPMI_INTERFACE="lanplus"
SOL_CIPHER_SUITE="3" # Cipher suite for high-security commands like SOL


# --- Helper Functions ---

# Function to display usage instructions
usage() {
    echo "Usage: $(basename "$0") <IP_ADDRESS> <COMMAND> [PASSWORD]"
    echo "   or: $(basename "$0") <COMMAND> <IP_ADDRESS> [PASSWORD]"
    echo ""
    echo "An advanced wrapper for common ipmitool functions."
    echo ""
    echo "Arguments:"
    echo "  IP_ADDRESS    The IP address of the BMC."
    echo "  COMMAND       The action to perform. See below."
    echo "  PASSWORD      (Optional) The BMC password. Defaults to the configured one."
    echo ""
    echo "Available Commands:"
    echo "  status, on, off, off-hard, reset, cycle, sol, lan, fru, sensors"
    echo ""
    echo "Example:"
    echo "  $(basename "$0") 10.180.131.5 reset"
    echo "  $(basename "$0") sol 10.180.131.5 MySecretPass123"
}

# Function to check if an argument is a valid command
is_command() {
    case "$1" in
        status|on|off|off-hard|reset|cycle|sol|lan|fru|sensors)
            return 0 # Success (it is a command)
            ;;
        *)
            return 1 # Failure (not a command)
            ;;
    esac
}

# Function to check if an argument looks like an IP address
is_ip() {
    # Simple regex check for IPv4 format
    if [[ "$1" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        return 0 # Success
    else
        return 1 # Failure
    fi
}


# --- Main Logic ---

# Check for minimum number of arguments or help flag
if [ "$#" -lt 2 ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
    usage
    exit 1
fi

# --- Intelligent Argument Parsing ---
IP_ADDR=""
COMMAND=""

# Process the first two arguments to identify IP and Command
for arg in "$1" "$2"; do
    if is_ip "$arg" && [ -z "$IP_ADDR" ]; then
        IP_ADDR="$arg"
    elif is_command "$arg" && [ -z "$COMMAND" ]; then
        COMMAND="$arg"
    fi
done

# Validate that we found both an IP and a Command
if [ -z "$IP_ADDR" ] || [ -z "$COMMAND" ]; then
    echo "Error: You must provide exactly one valid IP address and one command." >&2
    echo "       Found IP: '${IP_ADDR:-none}', Found Command: '${COMMAND:-none}'" >&2
    echo ""
    usage
    exit 1
fi

# Password is the (optional) third argument
PASSWORD="${3:-$DEFAULT_PASS}"


# --- Command Execution ---

# Use an array for robust argument passing
IPMI_ARGS=(
    -I "$IPMI_INTERFACE"
    -U "$IPMI_USER"
    -P "$PASSWORD"
    -H "$IP_ADDR"
)

echo "INFO: Executing command '${COMMAND}' on BMC at ${IP_ADDR}..."

# Add special cipher suite only for the SOL command
if [ "$COMMAND" == "sol" ]; then
    echo "INFO: Using higher security (Cipher Suite ${SOL_CIPHER_SUITE}) for SOL session."
    IPMI_ARGS+=(-C "$SOL_CIPHER_SUITE")
fi

# Append the actual ipmitool command and its sub-commands to the arguments array
case "$COMMAND" in
    status)   IPMI_ARGS+=(chassis power status);;
    on)       IPMI_ARGS+=(power on);;
    off)      echo "INFO: Sending graceful shutdown (ACPI) command..."; IPMI_ARGS+=(power soft);;
    off-hard) echo "WARNING: Forcing immediate power off!"; IPMI_ARGS+=(power off);;
    reset)    echo "INFO: Sending power reset command..."; IPMI_ARGS+=(power reset);;
    cycle)    echo "WARNING: Performing a hard power cycle!"; IPMI_ARGS+=(power cycle);;
    sol)
        echo "INFO: Activating Serial-over-LAN. Press '~.' (tilde followed by dot) to terminate the session."
        # Deactivate previous session first
        ipmitool "${IPMI_ARGS[@]}" sol deactivate >/dev/null 2>&1
        IPMI_ARGS+=(sol activate)
        ;;
    lan)      IPMI_ARGS+=(lan print);;
    fru)      IPMI_ARGS+=(fru print);;
    sensors)  IPMI_ARGS+=(sensor list);;
esac

# Execute the final command
ipmitool "${IPMI_ARGS[@]}"

# Check the exit code of the last command
if [ $? -ne 0 ]; then
    echo "Error: ipmitool command failed. Check IP address, credentials, and network connectivity." >&2
    exit 1
fi

echo "INFO: Command completed successfully."
